﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Web.Mvc;
using System.Web.Services.Protocols;
using System.Xml;
using System.Xml.Linq;
using Comissoes.Utilities;
using HtmlAgilityPack;
using NFe;

namespace Comissoes.Models
{
    public class NFeModel
    {
        private TNFe nfe { get; set; }
        private TCancNFe cancNFe { get; set; }
        private TInutNFe inutNFe { get; set; }
        private nfeProc nfeProc{ get; set; }
        private String arquivo { get; set; }
        private String cliente { get; set; }
        private String pasta { get; set; }
        public List<String> erros { get; set; }

        xcontEntities db = new xcontEntities();

        /// <summary>
        /// Confirma se a nota fiscal possui erros de validação
        /// </summary>
        /// <returns></returns>
        public Boolean SemErros()
        {
            return !this.erros.Any();
        }

        /// <summary>
        /// Adiciona o exception a lista de erros
        /// </summary>
        /// <param name="ex">Exception</param>
        private void AddException(Exception ex)
        {
            this.erros.Add(ex.Message);
            if (ex.InnerException != null)
            {
                erros.Add(ex.InnerException.Message);
            }
        }

        /// <summary>
        /// Construtor
        /// </summary>
        public NFeModel()
        {
            this.cliente = "Infopel";
        }

        /// <summary>
        /// Gerar e/ou atualizar arquivo TNFe xml
        /// </summary>
        /// <param name="nf">Nota Fiscal</param>
        /// <returns></returns>
        public void Update(NOTAS_FISCAIS nf)
        {
            PRODUTOS produto;
            String codbar;
            
            try
            {
                nf.VENDAS.ENDERECO_LOJAReference.Load();
                nf.VENDAS.ENDERECO_LOJA.ENDERECOSReference.Load();
                nf.VENDAS.ENDERECO_LOJA.ENDERECOS.BAIRROSReference.Load();
                nf.VENDAS.ENDERECO_LOJA.ENDERECOS.BAIRROS.CIDADESReference.Load();

                CIDADES cidade = nf.VENDAS.ENDERECO_LOJA.ENDERECOS.BAIRROS.CIDADES;
                cidade.UFSReference.Load();

                String indPag = "0";

                if (nf.VENDAS.CONDICOES_PAGAMENTO != null)
                {
                    if ((nf.VENDAS.CONDICOES_PAGAMENTO.PARCELAS_CDPG.HasValue
                        && nf.VENDAS.CONDICOES_PAGAMENTO.PARCELAS_CDPG > 1) ||
                        (nf.VENDAS.CONDICOES_PAGAMENTO.DIAS_CONDICAO_PAGAMENTO.Count() > 1))
                    {
                        indPag = "1";
                    }
                }

                #region infNFe

                this.nfe.infNFe = new TNFe.infNFeLocalType
                {
                    versao = nf.VERSAOXML_NF,
                    Id = String.Format("{0}", nf.CHAVENFE_NF),
                    ide = new TNFe.infNFeLocalType.ideLocalType
                    {
                        cUF = Convertions.tString(cidade.UFS.CODIBGE_UF),
                        cNF = nf.CHAVE_NF,
                        natOp = nf.VENDAS.NATUREZAS_OPERACAO.DESC_NTOP,
                        indPag = indPag,
                        mod = Convertions.tString(nf.MODELO_NF),
                        serie = Convertions.tString(nf.SERIE_NF),
                        nNF = nf.NUMERO_NF,
                        dEmi = DataString(nf.EMISSAO_NF),
                        dSaiEnt = DataString(nf.SAIENT_NF ?? DateTime.Now),
                        hSaiEnt = HoraString(nf.SAIENT_NF ?? DateTime.Now),
                        tpNF = nf.TIPOOP_NF,
                        cMunFG = cidade.CODIBGE_CID,

                        #region TNFe Referenciada TODO

                        /* this.nfe.infNFe.ide.NFref.Add(new TNFe.infNFeLocalType.ideLocalType.NFrefLocalType
                 * {
                 *      refNFe = "Nota fiscal vinculada",
                 *      refNF = new TNFe.infNFeLocalType.ideLocalType.NFrefLocalType.refNFLocalType
                 *      { // NF referenciada
                 *          cUF = "codigo IBGE",
                 *          AAMM = "Ano e mês de emissão da NF referenciada",
                 *          CNPJ = "cnpj do emitente",
                 *          mod = "modelo da nf",
                 *          serie = "serie da nf",
                 *          nNF = "numero da nf: 999999999"
                 *      },
                 *      refNFP = new TNFe.infNFeLocalType.ideLocalType.NFrefLocalType.refNFPLocalType
                 *      { // NF de produtor referenciada
                 *          cUF = "codigo IBGE",
                 *          AAMM = "Ano e mês de emissão da NF referenciada",
                 *          CNPJ = "cnpj do emitente",
                 *          IE = "cnpj do emitente",
                 *          mod = "modelo da nf",
                 *          serie = "serie da nf",
                 *          nNF = "numero da nf: 999999999",
                 * 
                 *      },
                 *      refECF = new TNFe.infNFeLocalType.ideLocalType.NFrefLocalType.refECFLocalType
                 *      { // Cupom fiscal vinculado
                 *          mod = "2B - não ECF, 2C - Cupom Fiscal PDV, 2D - Cupom Fiscal",
                 *          nECF = "Número de ordem seqüencial do ECF",
                 *          nCOO = "Número do Contador de Ordem de Operação"
                 *      }
                 *  });
                 */

                        #endregion

                        tpImp = Convertions.tString(nf.TIPODANFE_NF) ?? "1",
                        tpEmis = nf.TIPOEMISSAO_NF,
                        cDV = nf.DV_NF,
                        tpAmb = Convertions.tString(nf.AMBIENTE_NF) ?? "2",
                        finNFe = Convertions.tString(nf.FINALIDADE_NF),
                        procEmi = "0",
                        verProc = nf.VERSAOMR_NF
                    }
                };

                this.setEntidade(1, nf.VENDAS.LOJAS.COD_LOJA, nf.VENDAS.ENDERECO_LOJA.ID_ENPS,nf);
                this.setEntidade(2, nf.VENDAS.CLIENTES.COD_CLI, nf.VENDAS.ENDERECO_CLIENTE.ID_ENPS, nf);

                if (nf.VENDAS.ENDERECO_RETIRADA != null)
                {
                    this.setEndereco(4, nf.VENDAS.ENDERECO_RETIRADA.ID_ENPS);
                }

                if (nf.VENDAS.ENDERECO_ENTREGA != null)
                {
                    this.setEndereco(5, nf.VENDAS.ENDERECO_ENTREGA.ID_ENPS);
                }

                #endregion

                nf.VENDAS.ITENS_VENDA.Load();

                foreach (ITENS_VENDA iten in nf.VENDAS.ITENS_VENDA)
                {
                    iten.NATUREZAS_OPERACAOReference.Load();
                    iten.PRODUTOS_LISTAReference.Load();
                    iten.PRODUTOS_LISTA.PRODUTOSReference.Load();
                    iten.PRODUTOS_LISTA.PRODUTOS.CODIGOS_BARRA.Load();
                    iten.PRODUTOS_LISTA.PRODUTOS.UNIDADESReference.Load();
                    iten.PRODUTOS_LISTA.PRODUTOS.UNIDADES1Reference.Load();
                    iten.PRODUTOS_LISTA.PRODUTOS.SERVICOSReference.Load();
                    iten.VENDASReference.Load();
                    iten.VENDAS.PEDIDOS_VENDA.Load();
                    produto = iten.PRODUTOS_LISTA.PRODUTOS;
                    codbar = produto.CODIGOS_BARRA.OrderBy(t => t.PRINCIPAL_BAR).FirstOrDefault().COD_BAR;

                    #region prod

                    TNFe.infNFeLocalType.detLocalType.prodLocalType prod = new TNFe.infNFeLocalType.detLocalType.prodLocalType();
                    
                    prod.cProd = Convertions.tString(produto.COD_PROD);
                    prod.cEAN = codbar;
                    prod.xProd = produto.DESC_PROD;
                    prod.NCM = produto.NCM.COD_NCM;
                    if (!String.IsNullOrEmpty(iten.SIPI_ITVD)) prod.EXTIPI = iten.SIPI_ITVD;
                    prod.CFOP = Convertions.tString(iten.NATUREZAS_OPERACAO.CFOP_NTOP);
                    prod.uCom = produto.UNIDADES.COD_UNID;
                    prod.qCom = Convertions.tString(iten.QTDEENT_ITVD,4);
                    prod.vUnCom = Convertions.tString(iten.PRODUTOS_LISTA.PRECO_PDLS,10);
                    prod.vProd = Convertions.tString(iten.VLRTOT_ITVD,2);
                    prod.cEANTrib = codbar;
                    prod.uTrib = produto.UNIDADES1 == null ? produto.UNIDADES.COD_UNID : produto.UNIDADES1.COD_UNID;
                    prod.qTrib = Convertions.tString(iten.QTDEENT_ITVD * (produto.QTDEMB_PROD ?? 1),4);
                    prod.vUnTrib = Convertions.tString(iten.PRODUTOS_LISTA.PRECO_PDLS * (produto.QTDEMB_PROD ?? 1), 10);
                    prod.indTot = Convertions.tString(iten.INDTOT_ITVD);
                    if (iten.FRETE_ITVD.HasValue) prod.vFrete = Convertions.tString(iten.FRETE_ITVD,2);
                    if (iten.SEGURO_ITVD.HasValue) prod.vSeg = Convertions.tString(iten.SEGURO_ITVD, 2);
                    if (iten.DESCONTO_ITVD.HasValue) prod.vDesc = Convertions.tString(iten.DESCONTO_ITVD, 2);
                    if (iten.DESP_ACESSORIA_ITVD.HasValue) prod.vOutro = Convertions.tString(iten.DESP_ACESSORIA_ITVD, 2);
                    if (iten.VENDAS.PEDIDOS_VENDA.Any())
                    {
                        prod.xPed = iten.VENDAS.PEDIDOS_VENDA.First().NUMERO_PDVD;
                        prod.nItemPed = Convertions.tString(iten.ITEMPDVD_ITVD);
                    }
                    //DI = "TODO";
                    //veicProd = "TODO";
                    //med = "TODO";
                    //arma = "TODO";
                    //comb = "TODO"

                    #endregion

                    #region det

                    TNFe.infNFeLocalType.detLocalType det = new TNFe.infNFeLocalType.detLocalType();

                    det.nItem = Convertions.tString(iten.ITEM_ITVD);
                    if (!String.IsNullOrEmpty(det.infAdProd)) det.infAdProd = Convertions.tString(iten.INFOADI_ITVD);
                    det.prod = prod;
                    det.imposto = new TNFe.infNFeLocalType.detLocalType.impostoLocalType();

                    if (produto.SERVICOS == null)
                    {
                        #region Declaração de Importação TODO

                        /* List<NFe.infNFeLocalType.detLocalType.prodLocalType.DILocalType> DIs = new List<NFe.infNFeLocalType.detLocalType.prodLocalType.DILocalType>();
                         * 
                         * foreach (var j in db.EMAILS)
                         * {
                         *     TNFe.infNFeLocalType.detLocalType.prodLocalType.DILocalType DI = new TNFe.infNFeLocalType.detLocalType.prodLocalType.DILocalType
                         *     {
                         *         nDI = "",
                         *         dDI = "",
                         *         xLocDesemb = "",
                         *         UFDesemb = "",
                         *         dDesemb = "",
                         *         cExportador = ""
                         *     };
                         * 
                         *     foreach (var i in db.EMAILS)
                         *     {
                         *         DI.adi.Add(new TNFe.infNFeLocalType.detLocalType.prodLocalType.DILocalType.adiLocalType
                         *         {
                         *             nAdicao = "",
                         *             nSeqAdic = "",
                         *             cFabricante = "",
                         *             vDescDI = ""
                         *         });
                         *     }
                         * 
                         *     DIs.Add(DI);
                         * }
                         */

                        #endregion

                        #region ICMS

                        if (!String.IsNullOrEmpty(iten.SICMS_ITVD))
                        {
                            det.imposto.ICMS = new TNFe.infNFeLocalType.detLocalType.impostoLocalType.ICMSLocalType();

                            switch (iten.SICMS_ITVD)
                            {
                                case "00":
                                    det.imposto.ICMS.ICMS00 = new TNFe.infNFeLocalType.detLocalType.impostoLocalType.ICMSLocalType.ICMS00LocalType
                                    {
                                        orig = iten.OICMS_ITVD,
                                        CST = iten.SICMS_ITVD,
                                        modBC = iten.MICMS_ITVD,
                                        vBC = Convertions.tString(iten.BICMS_ITVD, 2),
                                        pICMS = Convertions.tString(iten.PICMS_ITVD, 2),
                                        vICMS = Convertions.tString(iten.ICMS_ITVD, 2)
                                    };
                                    break;
                                case "10":
                                    det.imposto.ICMS.ICMS10 = new TNFe.infNFeLocalType.detLocalType.impostoLocalType.ICMSLocalType.ICMS10LocalType
                                    {
                                        orig = iten.OICMS_ITVD,
                                        CST = iten.SICMS_ITVD,
                                        modBC = iten.MICMS_ITVD,
                                        vBC = Convertions.tString(iten.BICMS_ITVD, 2),
                                        pICMS = Convertions.tString(iten.PICMS_ITVD, 2),
                                        vICMS = Convertions.tString(iten.ICMS_ITVD, 2),
                                        modBCST = iten.MICMSST_ITVD,
                                        pMVAST = Convertions.tString(iten.MVAICMSST_ITVD, 2),
                                        pRedBCST = Convertions.tString(iten.RICMSST_ITVD, 2),
                                        vBCST = Convertions.tString(iten.BICMSST_ITVD, 2),
                                        pICMSST = Convertions.tString(iten.PICMSST_ITVD, 2),
                                        vICMSST = Convertions.tString(iten.ICMSST_ITVD, 2)
                                    };
                                    break;
                                case "|10":

                                    break;
                                case "20":
                                    det.imposto.ICMS.ICMS20 = new TNFe.infNFeLocalType.detLocalType.impostoLocalType.ICMSLocalType.ICMS20LocalType
                                    {
                                        orig = iten.OICMS_ITVD,
                                        CST = iten.SICMS_ITVD,
                                        modBC = iten.MICMS_ITVD,
                                        pRedBC = Convertions.tString(iten.RICMS_ITVD, 2),
                                        vBC = Convertions.tString(iten.BICMS_ITVD, 2),
                                        vICMS = Convertions.tString(iten.ICMS_ITVD, 2),
                                        pICMS = Convertions.tString(iten.PICMS_ITVD, 2),
                                    };
                                    break;
                                case "30":
                                    det.imposto.ICMS.ICMS30 = new TNFe.infNFeLocalType.detLocalType.impostoLocalType.ICMSLocalType.ICMS30LocalType
                                    {
                                        orig = iten.OICMS_ITVD,
                                        CST = iten.SICMS_ITVD,
                                        modBCST = iten.MICMSST_ITVD,
                                        pMVAST = Convertions.tString(iten.MVAICMSST_ITVD, 2),
                                        pRedBCST = Convertions.tString(iten.RICMSST_ITVD, 2),
                                        vBCST = Convertions.tString(iten.BICMSST_ITVD, 2),
                                        pICMSST = Convertions.tString(iten.PICMSST_ITVD, 2),
                                        vICMSST = Convertions.tString(iten.ICMSST_ITVD, 2)
                                    };
                                    break;
                                case "40":
                                    det.imposto.ICMS.ICMS40 = new TNFe.infNFeLocalType.detLocalType.impostoLocalType.ICMSLocalType.ICMS40LocalType
                                    {
                                        orig = iten.OICMS_ITVD,
                                        CST = iten.SICMS_ITVD,
                                        vICMS = Convertions.tString(iten.ICMS_ITVD, 2)
                                    };
                                    if (iten.ICMS_ITVD.HasValue) det.imposto.ICMS.ICMS40.motDesICMS = iten.MOTDESICMS_ITVD;
                                    break;
                                case "41":
                                    det.imposto.ICMS.ICMS40 = new TNFe.infNFeLocalType.detLocalType.impostoLocalType.ICMSLocalType.ICMS40LocalType
                                    {
                                        orig = iten.OICMS_ITVD,
                                        CST = iten.SICMS_ITVD,
                                        vICMS = Convertions.tString(iten.ICMS_ITVD, 2)
                                    };
                                    if (iten.ICMS_ITVD.HasValue) det.imposto.ICMS.ICMS40.motDesICMS = iten.MOTDESICMS_ITVD;
                                    break;
                                case "|41":
                                    det.imposto.ICMS.ICMSST = new TNFe.infNFeLocalType.detLocalType.impostoLocalType.ICMSLocalType.ICMSSTLocalType
                                    {
                                        orig = iten.OICMS_ITVD,
                                        CST = iten.SICMS_ITVD,
                                        vBCSTRet = Convertions.tString(iten.BICMSST_UF_REM_ITVD, 2),
                                        vICMSSTRet = Convertions.tString(iten.ICMSST_UF_REM_ITVD, 2),
                                        vBCSTDest = Convertions.tString(iten.BICMSST_UF_DEST_ITVD, 2),
                                        vICMSSTDest = Convertions.tString(iten.ICMSST_UF_DEST_ITVD, 2)
                                    };
                                    break;
                                case "50":

                                    break;
                                case "51":
                                    det.imposto.ICMS.ICMS51 = new TNFe.infNFeLocalType.detLocalType.impostoLocalType.ICMSLocalType.ICMS51LocalType
                                    {
                                        CST = iten.SICMS_ITVD,
                                        modBC = iten.MICMS_ITVD,
                                        orig = iten.OICMS_ITVD,
                                        pICMS = Convertions.tString(iten.PICMS_ITVD, 2),
                                        vBC = Convertions.tString(iten.BICMS_ITVD, 2),
                                        vICMS = Convertions.tString(iten.ICMS_ITVD, 2),
                                        pRedBC = Convertions.tString(iten.RICMS_ITVD, 2)
                                    };
                                    break;
                                case "60":
                                    det.imposto.ICMS.ICMS60 = new TNFe.infNFeLocalType.detLocalType.impostoLocalType.ICMSLocalType.ICMS60LocalType
                                    {
                                        orig = iten.OICMS_ITVD,
                                        CST = iten.SICMS_ITVD,
                                        vBCSTRet = Convertions.tString(iten.BICMSST_RETIDO_ITVD, 2),
                                        vICMSSTRet = Convertions.tString(iten.ICMSST_RETIDO_ITVD, 2)
                                    };
                                    break;
                                case "70":
                                    det.imposto.ICMS.ICMS70 = new TNFe.infNFeLocalType.detLocalType.impostoLocalType.ICMSLocalType.ICMS70LocalType
                                    {
                                        orig = iten.OICMS_ITVD,
                                        CST = iten.SICMS_ITVD,
                                        modBC = iten.MICMS_ITVD,
                                        pRedBCST = Convertions.tString(iten.RICMSST_ITVD, 2),
                                        vBC = Convertions.tString(iten.BICMS_ITVD, 2),
                                        pICMS = Convertions.tString(iten.PICMS_ITVD, 2),
                                        vICMS = Convertions.tString(iten.ICMS_ITVD, 2),
                                        modBCST = iten.MICMSST_ITVD,
                                        pMVAST = Convertions.tString(iten.MVAICMSST_ITVD, 2),
                                        pRedBC = Convertions.tString(iten.RICMS_ITVD, 2),
                                        vBCST = Convertions.tString(iten.BICMSST_ITVD, 2),
                                        pICMSST = Convertions.tString(iten.PICMSST_ITVD, 2),
                                        vICMSST = Convertions.tString(iten.ICMSST_ITVD, 2)
                                    };
                                    break;
                                case "90":
                                    det.imposto.ICMS.ICMS90 = new TNFe.infNFeLocalType.detLocalType.impostoLocalType.ICMSLocalType.ICMS90LocalType
                                    {
                                        orig = iten.OICMS_ITVD,
                                        CST = iten.SICMS_ITVD,
                                        modBC = iten.MICMS_ITVD,
                                        vBC = Convertions.tString(iten.BICMS_ITVD, 2),
                                        pRedBC = Convertions.tString(iten.RICMS_ITVD, 2),
                                        pICMS = Convertions.tString(iten.PICMS_ITVD, 2),
                                        vICMS = Convertions.tString(iten.ICMS_ITVD, 2),
                                        modBCST = iten.MICMSST_ITVD,
                                        pMVAST = Convertions.tString(iten.MVAICMSST_ITVD, 2),
                                        pRedBCST = Convertions.tString(iten.RICMSST_ITVD, 2),
                                        vBCST = Convertions.tString(iten.BICMSST_ITVD, 2),
                                        pICMSST = Convertions.tString(iten.PICMSST_ITVD, 2),
                                        vICMSST = Convertions.tString(iten.ICMSST_ITVD, 2)
                                    };
                                    break;
                                case "|90":
                                    det.imposto.ICMS.ICMSPart = new TNFe.infNFeLocalType.detLocalType.impostoLocalType.ICMSLocalType.ICMSPartLocalType
                                    {
                                        orig = iten.OICMS_ITVD,
                                        CST = iten.SICMS_ITVD,
                                        modBC = iten.MICMS_ITVD,
                                        vBC = Convertions.tString(iten.BICMS_ITVD, 2),
                                        pRedBC = Convertions.tString(iten.RICMS_ITVD, 2),
                                        pICMS = Convertions.tString(iten.PICMS_ITVD, 2),
                                        vICMS = Convertions.tString(iten.ICMS_ITVD, 2),
                                        modBCST = iten.MICMSST_ITVD,
                                        pMVAST = Convertions.tString(iten.MVAICMSST_ITVD, 2),
                                        pRedBCST = Convertions.tString(iten.RICMSST_ITVD, 2),
                                        vBCST = Convertions.tString(iten.BICMSST_ITVD, 2),
                                        pICMSST = Convertions.tString(iten.PICMSST_ITVD, 2),
                                        vICMSST = Convertions.tString(iten.ICMSST_ITVD, 2),
                                        pBCOp = Convertions.tString(iten.ROPICMS_ITVD, 2),
                                        UFST = Convertions.tString(iten.UFS.CODIBGE_UF)
                                    };
                                    break;
                                case "101":
                                    det.imposto.ICMS.ICMSSN101 = new TNFe.infNFeLocalType.detLocalType.impostoLocalType.ICMSLocalType.ICMSSN101LocalType
                                    {
                                        orig = iten.OICMS_ITVD,
                                        CSOSN = iten.SICMS_ITVD,
                                        pCredSN = Convertions.tString(iten.PCREDICMS_ITVD, 2),
                                        vCredICMSSN = Convertions.tString(iten.CREDITOICMS_ITVD, 2)
                                    };
                                    break;
                                case "102":
                                    det.imposto.ICMS.ICMSSN102 = new TNFe.infNFeLocalType.detLocalType.impostoLocalType.ICMSLocalType.ICMSSN102LocalType
                                    {
                                        orig = iten.OICMS_ITVD,
                                        CSOSN = iten.SICMS_ITVD
                                    };
                                    break;
                                case "103":
                                    det.imposto.ICMS.ICMSSN102 = new TNFe.infNFeLocalType.detLocalType.impostoLocalType.ICMSLocalType.ICMSSN102LocalType
                                    {
                                        orig = iten.OICMS_ITVD,
                                        CSOSN = iten.SICMS_ITVD
                                    };
                                    break;
                                case "201":
                                    det.imposto.ICMS.ICMSSN201 = new TNFe.infNFeLocalType.detLocalType.impostoLocalType.ICMSLocalType.ICMSSN201LocalType
                                    {
                                        orig = iten.OICMS_ITVD,
                                        CSOSN = iten.SICMS_ITVD,
                                        modBCST = iten.MICMSST_ITVD,
                                        pMVAST = Convertions.tString(iten.MVAICMSST_ITVD, 2),
                                        pRedBCST = Convertions.tString(iten.RICMSST_ITVD, 2),
                                        vBCST = Convertions.tString(iten.BICMSST_ITVD, 2),
                                        pICMSST = Convertions.tString(iten.PICMSST_ITVD, 2),
                                        vICMSST = Convertions.tString(iten.ICMSST_ITVD, 2),
                                        pCredSN = Convertions.tString(iten.PCREDICMS_ITVD, 2),
                                        vCredICMSSN = Convertions.tString(iten.CREDITOICMS_ITVD, 2)
                                    };
                                    break;
                                case "202":
                                    det.imposto.ICMS.ICMSSN202 = new TNFe.infNFeLocalType.detLocalType.impostoLocalType.ICMSLocalType.ICMSSN202LocalType
                                    {
                                        orig = iten.OICMS_ITVD,
                                        CSOSN = iten.SICMS_ITVD,
                                        modBCST = iten.MICMSST_ITVD,
                                        pMVAST = Convertions.tString(iten.MVAICMSST_ITVD, 2),
                                        pRedBCST = Convertions.tString(iten.RICMSST_ITVD, 2),
                                        vBCST = Convertions.tString(iten.BICMSST_ITVD, 2),
                                        pICMSST = Convertions.tString(iten.PICMSST_ITVD, 2),
                                        vICMSST = Convertions.tString(iten.ICMSST_ITVD, 2)
                                    };
                                    break;
                                case "203":
                                    det.imposto.ICMS.ICMSSN202 = new TNFe.infNFeLocalType.detLocalType.impostoLocalType.ICMSLocalType.ICMSSN202LocalType
                                    {
                                        orig = iten.OICMS_ITVD,
                                        CSOSN = iten.SICMS_ITVD,
                                        modBCST = iten.MICMSST_ITVD,
                                        pMVAST = Convertions.tString(iten.MVAICMSST_ITVD, 2),
                                        pRedBCST = Convertions.tString(iten.RICMSST_ITVD, 2),
                                        vBCST = Convertions.tString(iten.BICMSST_ITVD, 2),
                                        pICMSST = Convertions.tString(iten.PICMSST_ITVD, 2),
                                        vICMSST = Convertions.tString(iten.ICMSST_ITVD, 2)
                                    };
                                    break;
                                case "300":
                                    det.imposto.ICMS.ICMSSN102 = new TNFe.infNFeLocalType.detLocalType.impostoLocalType.ICMSLocalType.ICMSSN102LocalType
                                    {
                                        orig = iten.OICMS_ITVD,
                                        CSOSN = iten.SICMS_ITVD
                                    };
                                    break;
                                case "400":
                                    det.imposto.ICMS.ICMSSN102 = new TNFe.infNFeLocalType.detLocalType.impostoLocalType.ICMSLocalType.ICMSSN102LocalType
                                    {
                                        orig = iten.OICMS_ITVD,
                                        CSOSN = iten.SICMS_ITVD
                                    };
                                    break;
                                case "500":
                                    det.imposto.ICMS.ICMSSN500 = new TNFe.infNFeLocalType.detLocalType.impostoLocalType.ICMSLocalType.ICMSSN500LocalType
                                    {
                                        orig = iten.OICMS_ITVD,
                                        CSOSN = iten.SICMS_ITVD,
                                        vBCSTRet = Convertions.tString(iten.BICMSST_RETIDO_ITVD, 2),
                                        vICMSSTRet = Convertions.tString(iten.ICMSST_RETIDO_ITVD, 2)
                                    };
                                    break;
                                case "900":
                                    det.imposto.ICMS.ICMSSN900 = new TNFe.infNFeLocalType.detLocalType.impostoLocalType.ICMSLocalType.ICMSSN900LocalType
                                    {
                                        orig = iten.OICMS_ITVD,
                                        CSOSN = iten.SICMS_ITVD,
                                        modBC = iten.MICMS_ITVD,
                                        vBC = Convertions.tString(iten.BICMS_ITVD, 2),
                                        pRedBC = Convertions.tString(iten.RICMS_ITVD, 2),
                                        pICMS = Convertions.tString(iten.PICMS_ITVD, 2),
                                        vICMS = Convertions.tString(iten.ICMS_ITVD, 2),
                                        modBCST = iten.MICMSST_ITVD,
                                        pMVAST = Convertions.tString(iten.MVAICMSST_ITVD, 2),
                                        pRedBCST = Convertions.tString(iten.RICMSST_ITVD, 2),
                                        vBCST = Convertions.tString(iten.BICMSST_ITVD, 2),
                                        pICMSST = Convertions.tString(iten.PICMSST_ITVD, 2),
                                        vICMSST = Convertions.tString(iten.ICMSST_ITVD, 2),
                                        pCredSN = Convertions.tString(iten.PCREDICMS_ITVD, 2),
                                        vCredICMSSN = Convertions.tString(iten.CREDITOICMS_ITVD, 2)
                                    };
                                    break;
                            }
                        }

                        #endregion

                        #region II

                        if (iten.II_ITVD.HasValue)
                        {
                            det.imposto.II = new TNFe.infNFeLocalType.detLocalType.impostoLocalType.IILocalType
                            {
                                vBC = Convertions.tString(iten.BII_ITVD, 2),
                                vDespAdu = Convertions.tString(iten.DESPADUII_ITVD, 2),
                                vII = Convertions.tString(iten.II_ITVD, 2),
                                vIOF = Convertions.tString(iten.IOFII_ITVD, 2)
                            };
                        }

                        #endregion

                        #region IPI

                        if (!String.IsNullOrEmpty(iten.SIPI_ITVD))
                        {
                            det.imposto.IPI = new TNFe.infNFeLocalType.detLocalType.impostoLocalType.IPILocalType
                            {
                                clEnq = iten.CENQIPI_ITVD,
                                CNPJProd = iten.CNPJIPI_ITVD,
                                cSelo = iten.SELOIPI_ITVD,
                                qSelo = Convertions.tString(iten.QSELOIPI_ITVD),
                                cEnq = iten.ENQIPI_ITVD
                            };

                            switch (iten.SIPI_ITVD)
                            {
                                case "00":
                                case "49":
                                case "50":
                                case "99":
                                    det.imposto.IPI.IPITrib.CST = Convertions.tString(iten.SIPI_ITVD, 2);
                                    det.imposto.IPI.IPITrib.vBC = Convertions.tString(iten.BIPI_ITVD, 2);
                                    det.imposto.IPI.IPITrib.pIPI = Convertions.tString(iten.PIPI_ITVD, 2);
                                    det.imposto.IPI.IPITrib.qUnid = Convertions.tString(iten.QIPI_ITVD, 2);
                                    det.imposto.IPI.IPITrib.vUnid = Convertions.tString(iten.VIPI_ITVD, 2);
                                    det.imposto.IPI.IPITrib.vIPI = Convertions.tString(iten.IPI_ITVD, 2);
                                    break;
                                default:
                                    det.imposto.IPI.IPINT.CST = iten.SIPI_ITVD;
                                    break;
                            }
                        }

                        #endregion

                        #region PIS

                        det.imposto.PIS = new TNFe.infNFeLocalType.detLocalType.impostoLocalType.PISLocalType();
                        switch (iten.SPIS_ITVD)
                        {
                            case "01":
                            case "02":
                                det.imposto.PIS.PISAliq = new TNFe.infNFeLocalType.detLocalType.impostoLocalType.PISLocalType.PISAliqLocalType
                                {
                                    CST = iten.SPIS_ITVD,
                                    vBC = Convertions.tString(iten.BPIS_ITVD, 2),
                                    pPIS = Convertions.tString(iten.PPIS_ITVD, 2),
                                    vPIS = Convertions.tString(iten.PIS_ITVD, 2)
                                };
                                break;
                            case "03":
                                det.imposto.PIS.PISQtde = new TNFe.infNFeLocalType.detLocalType.impostoLocalType.PISLocalType.PISQtdeLocalType
                                {
                                    CST = iten.SPIS_ITVD,
                                    qBCProd = Convertions.tString(iten.QPIS_ITVD, 2),
                                    vAliqProd = Convertions.tString(iten.PPIS_ITVD, 2),
                                    vPIS = Convertions.tString(iten.PIS_ITVD, 2)
                                };
                                break;
                            case "04":
                            case "06":
                            case "07":
                            case "08":
                            case "09":
                                det.imposto.PIS.PISNT = new TNFe.infNFeLocalType.detLocalType.impostoLocalType.PISLocalType.PISNTLocalType
                                {
                                    CST = iten.SPIS_ITVD
                                };
                                break;
                            case "99":
                                det.imposto.PIS.PISOutr = new TNFe.infNFeLocalType.detLocalType.impostoLocalType.PISLocalType.PISOutrLocalType();

                                det.imposto.PIS.PISOutr.CST = iten.SPIS_ITVD;

                                if (iten.TPIS_ITVD == "1")
                                {
                                    det.imposto.PIS.PISOutr.vBC = Convertions.tString(iten.BPIS_ITVD);
                                    det.imposto.PIS.PISOutr.pPIS = Convertions.tString(iten.PPIS_ITVD);
                                }

                                det.imposto.PIS.PISOutr.qBCProd = Convertions.tString(iten.QPIS_ITVD);

                                if (iten.TPIS_ITVD == "2")
                                {
                                    det.imposto.PIS.PISOutr.vAliqProd = Convertions.tString(iten.VPIS_ITVD);
                                    det.imposto.PIS.PISOutr.vPIS = Convertions.tString(iten.PIS_ITVD);
                                }

                                break;
                        }

                        if (iten.PISST_ITVD.HasValue)
                        {
                            det.imposto.PISST = new TNFe.infNFeLocalType.detLocalType.impostoLocalType.PISSTLocalType
                            {
                                vBC = Convertions.tString(iten.PISST_ITVD),
                                pPIS = Convertions.tString(iten.PPISST_ITVD),
                                qBCProd = Convertions.tString(iten.QPISST_ITVD),
                                vAliqProd = Convertions.tString(iten.VPISST_ITVD),
                                vPIS = Convertions.tString(iten.PISST_ITVD)
                            };
                        }

                        #endregion

                        #region COFINS

                        switch (iten.SCOFINS_ITVD)
                        {
                            case "01":
                            case "02":
                                det.imposto.COFINS.COFINSAliq = new TNFe.infNFeLocalType.detLocalType.impostoLocalType.COFINSLocalType.COFINSAliqLocalType
                                {
                                    CST = iten.SCOFINS_ITVD,
                                    vBC = Convertions.tString(iten.BCOFINS_ITVD),
                                    pCOFINS = Convertions.tString(iten.PCOFINS_ITVD),
                                    vCOFINS = Convertions.tString(iten.COFINS_ITVD)
                                };
                                break;
                            case "03":
                                det.imposto.COFINS.COFINSQtde = new TNFe.infNFeLocalType.detLocalType.impostoLocalType.COFINSLocalType.COFINSQtdeLocalType
                                {
                                    CST = iten.SCOFINS_ITVD,
                                    qBCProd = Convertions.tString(iten.QCOFINS_ITVD),
                                    vAliqProd = Convertions.tString(iten.PCOFINS_ITVD),
                                    vCOFINS = Convertions.tString(iten.COFINS_ITVD)
                                };
                                break;
                            case "04":
                            case "06":
                            case "07":
                            case "08":
                            case "09":
                                det.imposto.COFINS.COFINSNT = new TNFe.infNFeLocalType.detLocalType.impostoLocalType.COFINSLocalType.COFINSNTLocalType
                                {
                                    CST = iten.SCOFINS_ITVD
                                };
                                break;
                            case "99":
                                det.imposto.COFINS.COFINSOutr = new TNFe.infNFeLocalType.detLocalType.impostoLocalType.COFINSLocalType.COFINSOutrLocalType();

                                det.imposto.COFINS.COFINSOutr.CST = iten.SCOFINS_ITVD;

                                if (iten.TCOFINS_ITVD == "1")
                                {
                                    det.imposto.COFINS.COFINSOutr.vBC = Convertions.tString(iten.BCOFINS_ITVD);
                                    det.imposto.COFINS.COFINSOutr.pCOFINS = Convertions.tString(iten.PCOFINS_ITVD);
                                }

                                det.imposto.COFINS.COFINSOutr.qBCProd = Convertions.tString(iten.QCOFINS_ITVD);

                                if (iten.TCOFINS_ITVD == "2")
                                {
                                    det.imposto.COFINS.COFINSOutr.vAliqProd = Convertions.tString(iten.VCOFINS_ITVD);
                                    det.imposto.COFINS.COFINSOutr.vCOFINS = Convertions.tString(iten.COFINS_ITVD);
                                }

                                break;
                        }

                        if (iten.COFINSST_ITVD.HasValue)
                        {
                            det.imposto.COFINSST = new TNFe.infNFeLocalType.detLocalType.impostoLocalType.COFINSSTLocalType
                            {
                                vBC = Convertions.tString(iten.COFINSST_ITVD),
                                pCOFINS = Convertions.tString(iten.PCOFINSST_ITVD),
                                qBCProd = Convertions.tString(iten.QCOFINSST_ITVD),
                                vAliqProd = Convertions.tString(iten.VCOFINSST_ITVD),
                                vCOFINS = Convertions.tString(iten.COFINSST_ITVD)
                            };
                        }

                        #endregion
                    }
                    else
                    {
                        det.imposto.ISSQN = new TNFe.infNFeLocalType.detLocalType.impostoLocalType.ISSQNLocalType
                        {
                            vBC = Convertions.tString(iten.BISSQN_ITVD),
                            vAliq = Convertions.tString(iten.PISSQN_ITVD),
                            vISSQN = Convertions.tString(iten.ISSQN_ITVD),
                            cMunFG = iten.CIDADES.CODIBGE_CID,
                            cListServ = Convertions.tString(produto.SERVICOS.COD_SERV),
                            cSitTrib = iten.TISSQN_ITVD
                        };
                    }

                    #endregion

                    #region infAdProd

                    if (!String.IsNullOrEmpty(iten.INFOADI_ITVD)) det.infAdProd = Convertions.tString(iten.INFOADI_ITVD);

                    #endregion

                    this.nfe.infNFe.det.Add(det);
                }

                #region total

                this.nfe.infNFe.total = new TNFe.infNFeLocalType.totalLocalType();

                if (nf.VENDAS.ITENS_VENDA.Any(t => t.PRODUTOS_LISTA.PRODUTOS.SERVICOS == null))
                {
                    this.nfe.infNFe.total.ICMSTot = new TNFe.infNFeLocalType.totalLocalType.ICMSTotLocalType();

                    this.nfe.infNFe.total.ICMSTot.vBC = Convertions.tString(nf.VENDAS.BICMS_VDA, 2);
                    this.nfe.infNFe.total.ICMSTot.vICMS = Convertions.tString(nf.VENDAS.ICMS_VDA, 2);
                    this.nfe.infNFe.total.ICMSTot.vBCST = Convertions.tString(nf.VENDAS.BICMSST_VDA, 2);
                    this.nfe.infNFe.total.ICMSTot.vST = Convertions.tString(nf.VENDAS.ICMSST_VDA, 2);
                    this.nfe.infNFe.total.ICMSTot.vProd = Convertions.tString(nf.VENDAS.VLRMERC_VDA, 2);
                    this.nfe.infNFe.total.ICMSTot.vFrete = Convertions.tString(nf.VENDAS.FRETE_VDA, 2);
                    this.nfe.infNFe.total.ICMSTot.vSeg = Convertions.tString(nf.VENDAS.SEGURO_VDA, 2);
                    this.nfe.infNFe.total.ICMSTot.vDesc = Convertions.tString(nf.VENDAS.DESCONTO_VDA, 2);
                    this.nfe.infNFe.total.ICMSTot.vII = Convertions.tString(nf.VENDAS.II_VDA, 2);
                    this.nfe.infNFe.total.ICMSTot.vIPI = Convertions.tString(nf.VENDAS.IPI_VDA, 2);
                    this.nfe.infNFe.total.ICMSTot.vPIS = Convertions.tString(nf.VENDAS.PIS_VDA, 2);
                    this.nfe.infNFe.total.ICMSTot.vCOFINS = Convertions.tString(nf.VENDAS.COFINS_VDA, 2);
                    this.nfe.infNFe.total.ICMSTot.vOutro = Convertions.tString(nf.VENDAS.DESP_ACESSORIA_VDA, 2);
                    this.nfe.infNFe.total.ICMSTot.vNF = Convertions.tString(nf.VENDAS.VLRTOT_VDA, 2);
                }
                else
                {
                    this.nfe.infNFe.total.ISSQNtot = new TNFe.infNFeLocalType.totalLocalType.ISSQNtotLocalType
                    {
                        vServ = Convertions.tString(nf.VENDAS.VLRTOT_VDA, 2),
                        vBC = Convertions.tString(nf.VENDAS.BISSQN_VDA, 2),
                        vISS = Convertions.tString(nf.VENDAS.ISSQN_VDA, 2),
                        vPIS = Convertions.tString(nf.VENDAS.PIS_VDA, 2),
                        vCOFINS = Convertions.tString(nf.VENDAS.COFINS_VDA, 2),
                    };
                }

                this.nfe.infNFe.total.retTrib = new TNFe.infNFeLocalType.totalLocalType.retTribLocalType();

                if (nf.VENDAS.BIRRF_VDA.HasValue) this.nfe.infNFe.total.retTrib.vBCIRRF = Convertions.tString(nf.VENDAS.BIRRF_VDA, 2);
                if (nf.VENDAS.BPREV_VDA.HasValue) this.nfe.infNFe.total.retTrib.vBCRetPrev = Convertions.tString(nf.VENDAS.BPREV_VDA, 2);
                if (nf.VENDAS.IRRF_VDA.HasValue) this.nfe.infNFe.total.retTrib.vIRRF = Convertions.tString(nf.VENDAS.IRRF_VDA, 2);
                if (nf.VENDAS.RCOFINS_VDA.HasValue) this.nfe.infNFe.total.retTrib.vRetCOFINS = Convertions.tString(nf.VENDAS.RCOFINS_VDA, 2);
                if (nf.VENDAS.RCSLL_VDA.HasValue) this.nfe.infNFe.total.retTrib.vRetCSLL = Convertions.tString(nf.VENDAS.RCSLL_VDA, 2);
                if (nf.VENDAS.RPIS_VDA.HasValue) this.nfe.infNFe.total.retTrib.vRetPIS = Convertions.tString(nf.VENDAS.RPIS_VDA, 2);
                if (nf.VENDAS.RPREV_VDA.HasValue) this.nfe.infNFe.total.retTrib.vRetPrev = Convertions.tString(nf.VENDAS.RPREV_VDA, 2);

                if (nf.VENDAS.TRANSPORTADORES != null)
                {
                    this.nfe.infNFe.transp = new TNFe.infNFeLocalType.transpLocalType
                    {
                        modFrete = nf.VENDAS.MODFRETE_VDA.Trim()
                    };

                    setEntidade(3, nf.VENDAS.TRANSPORTADORES.COD_TRAN, nf.VENDAS.ENDERECO_TRANSPORTADOR.ID_ENPS, nf);

                    nf.VENDAS.NATUREZAS_OPERACAOReference.Load();
                    this.nfe.infNFe.transp.retTransp = new TNFe.infNFeLocalType.transpLocalType.retTranspLocalType
                    {
                        vServ = Convertions.tString(nf.VALOR_TRAN_NF, 2),
                        vBCRet = Convertions.tString(nf.BASECALC_TRAN_NF, 2),
                        pICMSRet = Convertions.tString(nf.ALIQ_TRAN_NF, 2),
                        vICMSRet = Convertions.tString(nf.ICMS_TRAN_NF, 2),
                        CFOP =  Convertions.tString(nf.VENDAS.NATUREZAS_OPERACAO.CFOP_NTOP),
                        cMunFG = nf.CIDADES.CODIBGE_CID
                    };

                    if (nf.VENDAS.TRANSPORTADORES.VEICULOS.Any())
                    {
                        VEICULOS veiculo = nf.VENDAS.TRANSPORTADORES.VEICULOS.First();

                        this.nfe.infNFe.transp.veicTransp = new TVeiculo
                        {
                            placa = veiculo.PLACA_VEIC,
                            UF = veiculo.CIDADES.UFS.SIGLA_UF,
                            RNTC = veiculo.RNTC_VEIC
                        };
                    }

                    nf.VOLUMES_NF.Load();

                    foreach (VOLUMES_NF volume in nf.VOLUMES_NF)
                    {
                        List<TNFe.infNFeLocalType.transpLocalType.volLocalType.lacresLocalType> lacres = new List<TNFe.infNFeLocalType.transpLocalType.volLocalType.lacresLocalType>();

                        volume.VOLUMESReference.Load();
                        volume.VOLUMES.LACRES.Load();

                        foreach (LACRES lacre in volume.VOLUMES.LACRES)
                        {
                            lacres.Add(new TNFe.infNFeLocalType.transpLocalType.volLocalType.lacresLocalType
                            {
                                nLacre = lacre.NUMERO_LACRE
                            });
                        }

                        TNFe.infNFeLocalType.transpLocalType.volLocalType vol = new TNFe.infNFeLocalType.transpLocalType.volLocalType();
                        if (volume.VOLUMES.QTDE_VOL.HasValue) vol.qVol = Convertions.tString(volume.VOLUMES.QTDE_VOL);
                        if (String.IsNullOrEmpty(volume.VOLUMES.ESPECIE_VOL)) vol.esp = volume.VOLUMES.ESPECIE_VOL;
                        if (String.IsNullOrEmpty(volume.VOLUMES.MARCA_VOL)) vol.marca = volume.VOLUMES.MARCA_VOL;
                        if (String.IsNullOrEmpty(volume.VOLUMES.NUMERACAO_VOL)) vol.nVol = volume.VOLUMES.NUMERACAO_VOL;
                        if (volume.VOLUMES.PESOLIQ_VOL.HasValue) vol.pesoL = Convertions.tString(volume.VOLUMES.PESOLIQ_VOL, 3);
                        if (volume.VOLUMES.PESOBRT_VOL.HasValue) vol.pesoB = Convertions.tString(volume.VOLUMES.PESOBRT_VOL, 3);
                        if (lacres.Any()) vol.lacres = lacres;

                        this.nfe.infNFe.transp.vol.Add(vol);
                    }
                }

                #endregion

                #region Duplicatas TODO



                #endregion

                #region infAdic

                if (!String.IsNullOrEmpty(nf.MENSAGEM_NF) || !String.IsNullOrEmpty(nf.OBS_NF))
                {
                    this.nfe.infNFe.infAdic = new TNFe.infNFeLocalType.infAdicLocalType
                    {
                        //infAdFisco = nf.MENSAGEM_NF ?? "",
                        infCpl = nf.OBS_NF ?? ""
                    };
                }

                #endregion

                this.SaveChanges(nf);
            }
            catch (Exception ex)
            {
                this.AddException(ex);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="tipo">A - Envio de Lote de NF-e: O nome do arquivo será o número do lote com extensão “-env-lot.xml”;
        ///                    B - Recibo: O nome do arquivo será o número do lote com extensão “-rec.xml”;
        ///                    C - Pedido do Resultado do Processamento do Lote de NF-e: O nome do arquivo será o número do recibo com extensão “-ped-rec.xml”;
        ///                    D - Resultado do Processamento do Lote de NF-e: O nome do arquivo será o número do recibo com extensão “-pro-rec.xml”;
        ///                    E - Denegação de Uso: O nome do arquivo será a chave de acesso completa com extensão “-den.xml”;
        ///                    F - Pedido de Cancelamento de NF-e: O nome do arquivo será a chave de acesso completa com extensão “-ped-can.xml”;
        ///                    G - Pedido de Inutilização de Numeração: O nome do arquivo será composto por: UF + Ano de inutilização + CNPJ do emitente + Modelo + Série + Número Inicial + Número Final com extensão “-ped-inu.xml”;
        ///                    H - Inutilização de Numeração: O nome do arquivo será composto por: Ano de inutilização + CNPJ do emitente + Modelo + Série + Número Inicial + Número Final com extensão “-inu.xml”;
        ///                    I - Pedido de Consulta Situação Atual da NF-e: O nome do arquivo será a chave de acesso completa com extensão “-ped-sit.xml”;
        ///                    J - Situação Atual da NF-e: O nome do arquivo será a chave de acesso completa com extensão “-sit.xml”;
        ///                    K - Pedido de Consulta do Status do Serviço: O nome do arquivo será: “AAAAMMDDTHHMMSS” do momento da consulta com extensão “-ped-sta.xml”;
        ///                    L - Transmitidas: Chave da nfe com extensão “-sta.xml”;
        ///                    M - Status do Serviço: O nome do arquivo será: “AAAAMMDDTHHMMSS” do momento da consulta com extensão “-sta.xml”;</param>
        /// <param name="CHAVENFE_NF">Chave da TNFe na Nota Fiscal</param>
        /// <returns></returns>
        public String LocalizarArquivoPorTipo(Char tipo, String CHAVENFE_NF)
        {
            if (!String.IsNullOrEmpty(CHAVENFE_NF) && String.IsNullOrEmpty(this.arquivo))
            {
                this.arquivo = CHAVENFE_NF;
            }

            String pasta;

            switch (tipo)
            {
                case 'A': // Envio de Lote
                    pasta = "EnvioLote/" + this.arquivo + "-env-lot";
                    break;
                case 'B': // Recibo
                    pasta = "Recibos/" + this.arquivo + "-rec";
                    break;
                case 'C': // Pedido do Resultado do Processamento do Lote de NF-e
                    pasta = "PedidosProcessosLotes/" + this.arquivo + "-ped-rec";
                    break;
                case 'D': // Resultado do Processamento do Lote de NF-e
                    pasta = "LotesProcessadas/" + this.arquivo + "-pro-rec";
                    break;
                case 'E': // Denegação de Uso
                    pasta = "Denegadas/" + this.arquivo + "-den";
                    break;
                case 'F': // Pedido de Cancelamento de NF-e
                    pasta = "Canceladas/" + this.arquivo + "-ped-canc";
                    break;
                case 'G': // Pedido de Inutilização de Numeração
                    pasta = "PedidosInutilizacao/" + this.arquivo + "-ped-inu";
                    break;
                case 'H': // Inutilização de Numeração
                    pasta = "Inutilizadas/" + this.arquivo + "-inu";
                    break;
                case 'I': // Pedido de Consulta Situação Atual da NF-e
                    pasta = "Gravadas/" + this.arquivo + "-ped-sit";
                    break;
                case 'J': // Situação Atual da NF-e
                    pasta = "Gravadas/" + this.arquivo + "-sit";
                    break;
                case 'K': // Pedido de Consulta do Status do Serviço
                    pasta = "Gravadas/" + this.arquivo + "-ped-sta";
                    break;
                case 'L': // Pedido de Consulta do Status do Serviço
                    pasta = "Transmitidas/" + this.arquivo + "-proc";
                    break;
                default: // Status do Serviço
                    pasta = "Gravadas/" + this.arquivo + "-sta";
                    break;
            }

            return System.Web.HttpContext.Current.Server.MapPath("~/Content/Clientes/" + pasta + ".xml");
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="tipo">A - Envio de Lote de NF-e: O nome do arquivo será o número do lote com extensão “-env-lot.xml”;
        ///                    B - Recibo: O nome do arquivo será o número do lote com extensão “-rec.xml”;
        ///                    C - Pedido do Resultado do Processamento do Lote de NF-e: O nome do arquivo será o número do recibo com extensão “-ped-rec.xml”;
        ///                    D - Resultado do Processamento do Lote de NF-e: O nome do arquivo será o número do recibo com extensão “-pro-rec.xml”;
        ///                    E - Denegação de Uso: O nome do arquivo será a chave de acesso completa com extensão “-den.xml”;
        ///                    F - Pedido de Cancelamento de NF-e: O nome do arquivo será a chave de acesso completa com extensão “-ped-can.xml”;
        ///                    G - Pedido de Inutilização de Numeração: O nome do arquivo será composto por: UF + Ano de inutilização + CNPJ do emitente + Modelo + Série + Número Inicial + Número Final com extensão “-ped-inu.xml”;
        ///                    H - Inutilização de Numeração: O nome do arquivo será composto por: Ano de inutilização + CNPJ do emitente + Modelo + Série + Número Inicial + Número Final com extensão “-inu.xml”;
        ///                    I - Pedido de Consulta Situação Atual da NF-e: O nome do arquivo será a chave de acesso completa com extensão “-ped-sit.xml”;
        ///                    J - Situação Atual da NF-e: O nome do arquivo será a chave de acesso completa com extensão “-sit.xml”;
        ///                    K - Pedido de Consulta do Status do Serviço: O nome do arquivo será: “AAAAMMDDTHHMMSS” do momento da consulta com extensão “-ped-sta.xml”;
        ///                    L - Transmitidas: Chave da nfe com extensão “-sta.xml”;
        ///                    M - Status do Serviço: O nome do arquivo será: “AAAAMMDDTHHMMSS” do momento da consulta com extensão “-sta.xml”;</param>
        /// <returns></returns>
        public String LocalizarArquivoPorTipo(Char tipo)
        {
            return this.LocalizarArquivoPorTipo(tipo, null);
        }

        /// <summary>
        /// Carregar informações da nota fiscal
        /// </summary>
        /// <param name="nf">Nota Fiscal</param>
        /// <param name="tipo">A - procNfe
        ///                    B - procCanc
        ///                    C - procInut</param>
        public void Load(NOTAS_FISCAIS nf, Char tipo)
        {
            try
            {
                String pasta = LocalizarArquivoPorTipo(tipo, nf.CHAVENFE_NF);

                XmlDocument xml = new XmlDocument();

                xml.Load(pasta);
                
                if (xml.GetElementsByTagName("infNfe").Count != 0)
                {
                    this.nfe = (TNFe)XElement.Parse(xml.OuterXml);
                }
                else if (xml.GetElementsByTagName("infCanc").Count != 0)
                {
                    this.cancNFe = (TCancNFe)XElement.Parse(xml.OuterXml);
                }
                else if (xml.GetElementsByTagName("infInut").Count != 0)
                {
                    this.inutNFe = (TInutNFe)XElement.Parse(xml.OuterXml);
                }
            }
            catch (Exception ex)
            {
                this.AddException(ex);
            }
        }

        /// <summary>
        /// Salvar as alterações do arquivo xml
        /// </summary>
        /// <param name="nf">Nota fiscal</param>
        public void SaveChanges(NOTAS_FISCAIS nf)
        {
            try
            {
                if (String.IsNullOrEmpty(this.arquivo))
                {
                    this.arquivo = nf.CHAVENFE_NF;
                }

                String pasta;

                switch (nf.STATUS_NF)
                {
                    case "A": // Digitada - Gravada
                    case "B": // Validada
                        pasta = this.cliente + "/NFe/Gravadas/" + this.arquivo + "-nfe";
                        break;
                    case "C": // Assinada
                        pasta = this.cliente + "/NFe/Assinadas/" + this.arquivo + "-nfe_assinada";
                        break;
                    case "D": // Rejeitada
                        pasta = this.cliente + "/NFe/Rejeitadas/" + this.arquivo + "-nfe_rejeitada";
                        break;
                    case "E": // Processada
                        pasta = this.cliente + "/NFe/Transmitidas/" + this.arquivo + "-nfe_processada";
                        break;
                    default: // Cancelada
                        pasta = this.cliente + "/NFe/Canceladas/" + this.arquivo + "-can";
                        break;
                }

                this.nfe.Untyped.Save(System.Web.HttpContext.Current.Server.MapPath("~/Content/Clientes/" + pasta + ".xml"));
            }
            catch (Exception ex)
            {
                AddException(ex);
            }
        }

        /// <param name="tipo">A - Envio de Lote de NF-e: O nome do arquivo será o número do lote com extensão “-env-lot.xml”;
        ///                    B - Recibo: O nome do arquivo será o número do lote com extensão “-rec.xml”;
        ///                    C - Pedido do Resultado do Processamento do Lote de NF-e: O nome do arquivo será o número do recibo com extensão “-ped-rec.xml”;
        ///                    D - Resultado do Processamento do Lote de NF-e: O nome do arquivo será o número do recibo com extensão “-pro-rec.xml”;
        ///                    E - Denegação de Uso: O nome do arquivo será a chave de acesso completa com extensão “-den.xml”;
        ///                    F - Pedido de Cancelamento de NF-e: O nome do arquivo será a chave de acesso completa com extensão “-ped-can.xml”;
        ///                    G - Pedido de Inutilização de Numeração: O nome do arquivo será composto por: UF + Ano de inutilização + CNPJ do emitente + Modelo + Série + Número Inicial + Número Final com extensão “-ped-inu.xml”;
        ///                    H - Inutilização de Numeração: O nome do arquivo será composto por: Ano de inutilização + CNPJ do emitente + Modelo + Série + Número Inicial + Número Final com extensão “-inu.xml”;
        ///                    I - Pedido de Consulta Situação Atual da NF-e: O nome do arquivo será a chave de acesso completa com extensão “-ped-sit.xml”;
        ///                    J - Situação Atual da NF-e: O nome do arquivo será a chave de acesso completa com extensão “-sit.xml”;
        ///                    K - Pedido de Consulta do Status do Serviço: O nome do arquivo será: “AAAAMMDDTHHMMSS” do momento da consulta com extensão “-ped-sta.xml”;
        ///                    L - Transmitidas e Aceita: Chave da nfe com extensão “-procNfe.xml”;
        ///                    M - Status do Serviço: O nome do arquivo será: “AAAAMMDDTHHMMSS” do momento da consulta com extensão “-sta.xml”;</param>
        /// <returns></returns>
        public void SaveChanges(NOTAS_FISCAIS nf, Char tipo, XElement Untyped)
        {
            try
            {
                if (String.IsNullOrEmpty(this.arquivo))
                {
                    this.arquivo = nf.CHAVENFE_NF;
                }

                String pasta = LocalizarArquivoPorTipo(tipo);

                Untyped.Save(pasta);
            }
            catch (Exception ex)
            {
                this.AddException(ex);
            }
        }

        /// <summary>
        /// Assinar a TNFe
        /// </summary>
        /// <param name="RefUri"></param>
        /// <param name="caminhoCertificado"></param>
        /// <param name="passwdCertificado"></param>
        /// <param name="nf"></param>
        public void Assinar(String RefUri, XElement Untyped)
        {
            AssinaturaDigital AD = new AssinaturaDigital();
            X509Certificate2 Certificado = new X509Certificate2();

            Certificado certificado = new Certificado();
            Certificado = certificado.Localizar();

            erros.Union(AD.Assinar(Serializadores.SerializeXMLObject(Untyped), RefUri, Certificado));

            if (this.SemErros())
            {
                switch (RefUri)
                {
                    case "infNFe":
                        this.nfe = (TNFe)XElement.Parse(AD.XMLStringAssinado);
                        break;
                    case "infCanc":
                        this.cancNFe = (TCancNFe)XElement.Parse(AD.XMLStringAssinado);
                        break;
                    case "infInut":
                        this.inutNFe = (TInutNFe)XElement.Parse(AD.XMLStringAssinado);
                        break;
                }
            }
        }

        /// <summary>
        /// Transmitir a TNFe
        /// </summary>
        /// <param name="nf"></param>
        public void Transmitir(NOTAS_FISCAIS nf)
        {
            try
            {
                #region LoadUF

                nf.VENDASReference.Load();
                nf.VENDAS.ENDERECO_LOJAReference.Load();
                nf.VENDAS.ENDERECO_LOJA.ENDERECOSReference.Load();
                nf.VENDAS.ENDERECO_LOJA.ENDERECOS.BAIRROSReference.Load();
                nf.VENDAS.ENDERECO_LOJA.ENDERECOS.BAIRROS.CIDADESReference.Load();
                nf.VENDAS.ENDERECO_LOJA.ENDERECOS.BAIRROS.CIDADES.UFSReference.Load();

                #endregion

                UFS UF = nf.VENDAS.ENDERECO_LOJA.ENDERECOS.BAIRROS.CIDADES.UFS;

                String WebService = GetWebService("NfeRecepcao", UF.SIGLA_UF, nf.AMBIENTE_NF);
                if (string.IsNullOrEmpty(WebService))
                {
                    erros.Add("WebService não localizado.");
                }
                else
                {
                    this.Load(nf, 'A');

                    this.Update(nf);

                    Comissoes.NfeRecepcao2.NfeRecepcao2 ws = new Comissoes.NfeRecepcao2.NfeRecepcao2(WebService)
                    {
                        nfeCabecMsgValue = new NfeRecepcao2.nfeCabecMsg
                        {
                            cUF = UF.CODIBGE_UF.ToString(),
                            versaoDados = "2.00"
                        },
                        SoapVersion = SoapProtocolVersion.Soap12
                    };

                    Certificado cert = new Certificado();
                    X509Certificate2 certificado = new X509Certificate2();
                    certificado = cert.Localizar();

                    ws.ClientCertificates.Add(certificado);

                    this.Assinar("infNFe", this.nfe.Untyped);

                    XmlDocument xml = XmlExtensions.ToXmlDocument(this.nfe.Untyped);
                    XmlNode xmlNode = ws.nfeRecepcaoLote2(xml);

                    TRetEnviNFe retorno = (TRetEnviNFe)XElement.Parse(xmlNode.OuterXml);

                    this.nfeProc = new nfeProc();
                    this.nfeProc.NFe = this.nfe;

                    nfeProc.protNFe = new TProtNFe
                    {
                        versao = retorno.verAplic,
                        infProt = new TProtNFe.infProtLocalType
                        {
                            Id = "ID" + retorno.infRec.nRec,
                            tpAmb = retorno.tpAmb,
                            verAplic = retorno.verAplic,
                            chNFe = nf.CHAVENFE_NF,
                            dhRecbto = retorno.dhRecbto,
                            nProt = retorno.tpAmb,
                            //digVal = nfe.Signature,
                            cStat = retorno.cStat,
                            xMotivo = retorno.xMotivo
                        }
                    };

                    ws.Dispose();

                    this.SaveChanges(null, 'L', this.nfeProc.Untyped);
                }
            }
            catch (Exception ex)
            {
                AddException(ex);
            }
        }

        /// <summary>
        /// Validar cancelamento da nfe
        /// </summary>
        /// <param name="form"></param>
        private void ValidarCancelamento(FormCollection form)
        {
            if (String.IsNullOrEmpty(form["ID_NF"])) this.erros.Add("Nota Fiscal não localizada.");
            if (String.IsNullOrEmpty(form["AMBIENTE_NF"])) this.erros.Add("É necessário informar o tipo de ambiente.");
        }

        /// <summary>
        /// Cancelar a TNFe
        /// </summary>
        /// <param name="nf"></param>
        public void Cancelar(FormCollection form)
        {
            try
            {
                Int32? ID_NF = Convertions.Inteiro(form["ID_NF"]);
                NOTAS_FISCAIS nf = db.NOTAS_FISCAIS.First(t=>t.ID_NF == ID_NF);

                #region LoadUF

                nf.VENDASReference.Load();
                nf.VENDAS.ENDERECO_LOJAReference.Load();
                nf.VENDAS.ENDERECO_LOJA.ENDERECOSReference.Load();
                nf.VENDAS.ENDERECO_LOJA.ENDERECOS.BAIRROSReference.Load();
                nf.VENDAS.ENDERECO_LOJA.ENDERECOS.BAIRROS.CIDADESReference.Load();
                nf.VENDAS.ENDERECO_LOJA.ENDERECOS.BAIRROS.CIDADES.UFSReference.Load();

                #endregion

                UFS UF = nf.VENDAS.ENDERECO_LOJA.ENDERECOS.BAIRROS.CIDADES.UFS;

                String WebService = GetWebService("NfeCancelamento", UF.SIGLA_UF, nf.AMBIENTE_NF);
                if (String.IsNullOrEmpty(WebService))
                {
                    erros.Add("WebService não localizado.");
                }
                else
                {
                    this.Load(null, 'B');

                    Comissoes.NfeCancelamento2.NfeCancelamento2 ws = new Comissoes.NfeCancelamento2.NfeCancelamento2(WebService)
                    {
                        nfeCabecMsgValue = new NfeCancelamento2.nfeCabecMsg
                        {
                            cUF = UF.CODIBGE_UF.ToString(),
                            versaoDados = "2.00"
                        },
                        SoapVersion = SoapProtocolVersion.Soap12
                    };

                    Certificado cert = new Certificado();
                    X509Certificate2 certificado = new X509Certificate2();
                    certificado = cert.Localizar();

                    ws.ClientCertificates.Add(certificado);
                    procCancNFe procCancNFe = new NFe.procCancNFe
                    {
                        cancNFe = new TCancNFe
                        {
                            infCanc = new TCancNFe.infCancLocalType
                            {
                                Id = this.nfe.infNFe.Id,
                                tpAmb = form["AMBIENTE_NF"],
                                xServ = "CANCELAR",
                                chNFe = nf.CHAVENFE_NF,
                                
                                xJust = form["JUSTCAN_NF"]
                            }
                        }
                    };

                    this.Assinar("cancNFe", procCancNFe.cancNFe.Untyped);

                    XmlDocument xml = XmlExtensions.ToXmlDocument(this.cancNFe.Untyped);
                    XmlNode xmlNode = ws.nfeCancelamentoNF2(xml);

                    TRetEnviNFe retorno = (TRetEnviNFe)XElement.Parse(xmlNode.OuterXml);

                    ws.Dispose();

                    this.SaveChanges(null, 'H', this.inutNFe.Untyped);
                }
            }
            catch (Exception ex)
            {
                AddException(ex);
            }
        }

        /// <summary>
        /// Validar os dados de inutilização da NF
        /// </summary>
        /// <param name="form"></param>
        private void ValidarInutilizacao(FormCollection form)
        {
            if (String.IsNullOrEmpty(form["COD_LOJA"])) this.erros.Add("É necessário informar a loja.");
            if (String.IsNullOrEmpty(form["AMBIENTE_NF"])) this.erros.Add("É necessário informar o tipo de ambiente da NF.");            
            if (String.IsNullOrEmpty(form["SERIE_NF"])) this.erros.Add("É necessário informar a série das notas fiscais.");
            if (String.IsNullOrEmpty(form["JUSTCAN_NF"])) this.erros.Add("É necessário informar a justificativa da inutilização");
            
            Int64? NF_INI = Convertions.Inteiro(form["NF_INI"]), NF_FIN = Convertions.Inteiro(form["NF_FIN"]);
            if (!NF_INI.HasValue) this.erros.Add("É necessário informar o número da nota fiscal inicial.");
            if (!NF_FIN.HasValue) this.erros.Add("É necessário informar o número da nota fiscal final.");
            if ((NF_INI ?? 0) > (NF_FIN ?? 0)) this.erros.Add("O número inicial não pode ser maior que o número final.");

            Int32? COD_LOJA = Convertions.Inteiro(form["COD_LOJA"]);
            LOJAS loja = db.LOJAS
                           .Include("PESSOAS")
                           .Include("PESSOAS.DOCUMENTOS_PESSOA")
                           .Include("PESSOAS.DOCUMENTOS_PESSOA.DOCUMENTOS")
                           .Include("PESSOAS.ENDERECOS_PESSOA").FirstOrDefault(t => t.COD_LOJA == COD_LOJA);
            if (!loja.PESSOAS.DOCUMENTOS_PESSOA.Any(t=> t.DOCUMENTOS.COD_DOC == 2))
            {
                erros.Add("Loja não possui cnpj cadastrado.");
            }
            if (!loja.PESSOAS.ENDERECOS_PESSOA.Any())
            {
                erros.Add("Loja não possui endereços");
            }
        }

        /// <summary>
        /// Cancelar a TNFe
        /// </summary>
        /// <param name="nf"></param>
        public void Inutilizar(FormCollection form)
        {
            try
            {
                this.ValidarInutilizacao(form);

                if (SemErros())
                {
                    Int32? COD_LOJA = Convertions.Inteiro(form["COD_LOJA"]);
                    Int32? AMBIENTE_NF = Convertions.Inteiro(form["AMBIENTE_NF"]);

                    LOJAS loja = db.LOJAS.FirstOrDefault(t => t.COD_LOJA == COD_LOJA);
                    loja.PESSOASReference.Load();
                    loja.PESSOAS.ENDERECOS_PESSOA.Load();
                    loja.PESSOAS.DOCUMENTOS_PESSOA.Load();

                    ENDERECOS_PESSOA endereco = loja.PESSOAS.ENDERECOS_PESSOA.First();
                    endereco.ENDERECOSReference.Load();
                    endereco.ENDERECOS.BAIRROSReference.Load();
                    endereco.ENDERECOS.BAIRROS.CIDADESReference.Load();
                    endereco.ENDERECOS.BAIRROS.CIDADES.UFSReference.Load();

                    DOCUMENTOS_PESSOA cnpj = loja.PESSOAS.DOCUMENTOS_PESSOA.First(t => t.DOCUMENTOS.COD_DOC == 2);

                    String SIGLA_UF = endereco.ENDERECOS.BAIRROS.CIDADES.UFS.SIGLA_UF,
                           ANO_NF = DateTime.Now.Year.ToString().Substring(2);

                    String WebService = GetWebService("NfeInutilizacao", SIGLA_UF, AMBIENTE_NF);
                    if (String.IsNullOrEmpty(WebService))
                    {
                        erros.Add("WebService não localizado.");
                    }
                    else
                    {
                        Comissoes.NfeInutilizacao2.NfeInutilizacao2 ws = new Comissoes.NfeInutilizacao2.NfeInutilizacao2(WebService)
                        {
                            nfeCabecMsgValue = new Comissoes.NfeInutilizacao2.nfeCabecMsg
                            {
                                cUF = SIGLA_UF,
                                versaoDados = "2.00"
                            },

                            SoapVersion = SoapProtocolVersion.Soap12
                        };

                        Certificado cert = new Certificado();
                        X509Certificate2 certificado = new X509Certificate2();
                        certificado = cert.Localizar();

                        ws.ClientCertificates.Add(certificado);
                        
                        ProcInutNFe procInutNfe = new ProcInutNFe
                        {
                            inutNFe = new TInutNFe
                            {
                                infInut = new TInutNFe.infInutLocalType
                                {
                                    Id = String.Format("ID{0}{1}{2}55{3}{4}{5}", SIGLA_UF, ANO_NF, cnpj.VALOR_PSDC, form["SERIE_NF"], form["NF_INI"], form["NF_FIN"]),
                                    tpAmb = form["AMBIENTE_NF"],
                                    xServ = "INUTILIZAR",
                                    cUF = SIGLA_UF,
                                    ano = ANO_NF,
                                    CNPJ = cnpj.VALOR_PSDC,
                                    mod = "55",
                                    serie = form["SERIE_NF"],
                                    nNFIni = form["NF_INI"],
                                    nNFFin = form["NF_FIN"],
                                    xJust = form["JUSTINUT_NF"]
                                }
                            }
                        };

                        this.Assinar("inutNFe", procInutNfe.inutNFe.Untyped);

                        XmlDocument xml = XmlExtensions.ToXmlDocument(this.inutNFe.Untyped);
                        XmlNode xmlNode = ws.nfeInutilizacaoNF2(xml);

                        TRetEnviNFe retorno = (TRetEnviNFe)XElement.Parse(xmlNode.OuterXml);

                        ws.Dispose();
                        
                        this.SaveChanges(null, 'H', this.inutNFe.Untyped);
                    }
                }
            }
            catch (Exception ex)
            {
                AddException(ex);
            }
        }

        /// <summary>
        /// Retorna a URL do servico padrao com base no tipo do webservice e na UF do emitente
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        private String GetWebService(String tipo, String UF, Int32? Ambiente)
        {
            HtmlWeb html = new HtmlWeb();

            HtmlWeb oWeb = new HtmlAgilityPack.HtmlWeb();

            HtmlDocument htmlDoc;
            switch (Ambiente)
            {
                case 1: // Produção
                    htmlDoc = oWeb.Load("http://www.nfe.fazenda.gov.br/portal/WebServices.aspx");
                    break;
                default: // Homologação
                    htmlDoc = oWeb.Load("http://hom.nfe.fazenda.gov.br/portal/WebServices.aspx");
                    break;
            }

            HtmlNode raiz = htmlDoc.DocumentNode;
            HtmlNode tabela = raiz.SelectSingleNode("//table[@id ='ctl00_ContentPlaceHolder3_GridView1']");

            IEnumerable<HtmlNode> linhas = tabela.ChildNodes.Where(t => t.ChildNodes.Count == 6);
            foreach (HtmlNode linha in linhas)
            {
                if (linha.ChildNodes[1].InnerText == UF &&
                    linha.ChildNodes[2].InnerText == tipo &&
                    linha.ChildNodes[3].InnerText == "2.00")
                {
                    return linha.ChildNodes[4].InnerText;
                }
            }

            foreach (HtmlNode linha in linhas)
            {
                if (linha.ChildNodes[1].InnerText == "SVAN" &&
                    linha.ChildNodes[2].InnerText == tipo &&
                    linha.ChildNodes[3].InnerText == "2.00")
                {
                    return linha.ChildNodes[4].InnerText;
                }
            }

            return string.Empty;
        }

        /// <summary>
        /// Converte uma string de data no formato dd/MM/yyyy para yyyy-MM-dd
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        private String DataString(DateTime? data)
        {
            if (data.HasValue)
            {
                return String.Format("{0:yyyy-MM-dd}", data);
            }
            else
            {
                return null;
            }
        }

        /// <summary>
        /// Converte uma string de data no formato dd/MM/yyyy para yyyy-MM-dd
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        private String HoraString(DateTime? data)
        {
            if (data.HasValue)
            {
                return String.Format("{0:HH:mm:ss}", data);
            }
            else
            {
                return null;
            }
        }

        /// <summary>
        /// Converte uma string de data no formato dd/MM/yyyy para yyyy-MM-dd
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        private String DataString(String data)
        {
            try
            {
                return String.Format("{0:yyyy-MM-dd}", DateTime.Parse(data));
            }
            catch
            {
                return null;
            }
        }

        /// <summary>
        /// Converte uma string de data no formato yyyy-MM-dd/yyyyMMdd para dd/MM/yyyy
        /// </summary>
        /// <param name="data"></param>
        /// <returns>String</returns>
        private String StringDataString(String data)
        {
            try
            {
                data = data.Replace("-", "");
                return String.Format("{0}/{1}/{2}", data.Substring(8, 2), data.Substring(5, 2), data.Substring(0, 4));
            }
            catch
            {
                return String.Empty;
            }
        }

        /// <summary>
        /// Converte uma string de data no formato yyyy-MM-dd/yyyyMMdd para dd/MM/yyyy
        /// </summary>
        /// <param name="data"></param>
        /// <returns>String</returns>
        private DateTime StringData(String data)
        {
            return DateTime.Parse(data);
        }

        /// <summary>
        /// Converte uma data no formato yyyy-MM-dd/yyyyMMdd para datetime
        /// </summary>
        /// <param name="data"></param>
        /// <param name="datetime"></param>
        /// <returns></returns>
        private DateTime StringData(String data, Boolean datetime)
        {
            return DateTime.Parse(String.Format("{0}/{1}/{2}", data.Substring(8, 2), data.Substring(5, 2), data.Substring(0, 4)));
        }

        /// <summary>
        /// Registra as entidades da Nota Fiscal
        /// </summary>
        /// <param name="tipo">1 - Loja
        ///                    2 - Cliente
        ///                    3 - Transportador
        ///                    4 - Endereço diferente da loja
        ///                    5 - Endereço diferente do cliente</param>
        /// <param name="COD_PESSOA"></param>
        /// <param name="ID_ENPS"></param>
        /// <param name="nf">Nota Fiscal</param>
        public void setEntidade(Int32 tipo, Int32 COD_PESSOA, Int32 ID_ENPS,NOTAS_FISCAIS nf)
        {
            try
            {
                xcontEntities db = new xcontEntities();
                PESSOAS pessoa;

                switch (tipo)
                {
                    case 1:
                    case 4:
                        pessoa = db.LOJAS.Include("PESSOAS").FirstOrDefault(t => t.COD_LOJA == COD_PESSOA).PESSOAS;
                        break;
                    case 2:
                    case 5:
                        pessoa = db.CLIENTES.Include("PESSOAS").FirstOrDefault(t => t.COD_CLI == COD_PESSOA).PESSOAS;
                        break;
                    default:
                        pessoa = db.TRANSPORTADORES.Include("PESSOAS").FirstOrDefault(t => t.COD_TRAN == COD_PESSOA).PESSOAS;
                        break;
                }

                ENDERECOS_PESSOA ENDERECO_PESSOA = db.ENDERECOS_PESSOA.FirstOrDefault(t => t.PESSOAS.ID_PESSOA == pessoa.ID_PESSOA);
                IQueryable<DOCUMENTOS_PESSOA> DOCUMENTOS_PESSOA = db.DOCUMENTOS_PESSOA.Include("DOCUMENTOS").Where(t => t.PESSOAS.ID_PESSOA == pessoa.ID_PESSOA);

                if (ENDERECO_PESSOA == null)
                {
                    erros.Add("Entidade não possui possui endereços cadastrados");
                    return;
                }

                if (!DOCUMENTOS_PESSOA.Any(t => t.DOCUMENTOS.COD_DOC == 1 || t.DOCUMENTOS.COD_DOC == 2))
                {
                    erros.Add("Entidade não possui CPF ou CNPJ");
                    return;
                }

                switch (tipo)
                {
                    case 1:
                        LOJAS loja = db.LOJAS.Include("REGIMES_TRIBUTARIOS").First(t => t.PESSOAS.ID_PESSOA == pessoa.ID_PESSOA);

                        this.nfe.infNFe.emit = new TNFe.infNFeLocalType.emitLocalType();
                        if (DOCUMENTOS_PESSOA.Any(t => t.DOCUMENTOS.COD_DOC == 1))
                        {
                            this.nfe.infNFe.emit.CPF = DOCUMENTOS_PESSOA.FirstOrDefault(t => t.DOCUMENTOS.COD_DOC == 1).VALOR_PSDC;
                        }
                        else
                        {
                            this.nfe.infNFe.emit.CNPJ = DOCUMENTOS_PESSOA.FirstOrDefault(t => t.DOCUMENTOS.COD_DOC == 2).VALOR_PSDC;
                        }

                        this.nfe.infNFe.emit.xNome = pessoa.NOME_PESSOA;
                        this.nfe.infNFe.emit.xFant = pessoa.FANTASIA_PESSOA;
                        this.setEndereco(1, ID_ENPS);

                        if (DOCUMENTOS_PESSOA.Any(t => t.DOCUMENTOS.COD_DOC == 3))
                        {
                            this.nfe.infNFe.emit.IE = DOCUMENTOS_PESSOA.FirstOrDefault(t => t.DOCUMENTOS.COD_DOC == 3).VALOR_PSDC;
                        }
                        if (DOCUMENTOS_PESSOA.Any(t => t.DOCUMENTOS.COD_DOC == 4))
                        {
                            this.nfe.infNFe.emit.IM = DOCUMENTOS_PESSOA.FirstOrDefault(t => t.DOCUMENTOS.COD_DOC == 4).VALOR_PSDC;
                        }
                        if (DOCUMENTOS_PESSOA.Any(t => t.DOCUMENTOS.COD_DOC == 5))
                        {
                            this.nfe.infNFe.emit.CNAE = DOCUMENTOS_PESSOA.FirstOrDefault(t => t.DOCUMENTOS.COD_DOC == 5).VALOR_PSDC;
                        }

                        this.nfe.infNFe.emit.CRT = Convertions.tString(loja.REGIMES_TRIBUTARIOS.ID_RGTR);

                        break;
                    case 2:
                        this.nfe.infNFe.dest = new TNFe.infNFeLocalType.destLocalType();
                        if (DOCUMENTOS_PESSOA.Any(t => t.DOCUMENTOS.COD_DOC == 1))
                        {
                            this.nfe.infNFe.dest.CPF = DOCUMENTOS_PESSOA.FirstOrDefault(t => t.DOCUMENTOS.COD_DOC == 1).VALOR_PSDC;
                        }
                        else
                        {
                            this.nfe.infNFe.dest.CNPJ = DOCUMENTOS_PESSOA.FirstOrDefault(t => t.DOCUMENTOS.COD_DOC == 2).VALOR_PSDC;
                        }

                        this.nfe.infNFe.dest.xNome = pessoa.NOME_PESSOA;
                        this.setEndereco(2, ID_ENPS);

                        if (DOCUMENTOS_PESSOA.Any(t => t.DOCUMENTOS.COD_DOC == 3))
                        {
                            this.nfe.infNFe.dest.IE = DOCUMENTOS_PESSOA.FirstOrDefault(t => t.DOCUMENTOS.COD_DOC == 3).VALOR_PSDC;
                        }

                        this.nfe.infNFe.dest.email = db.EMAILS.FirstOrDefault(t => t.PESSOAS.ID_PESSOA == pessoa.ID_PESSOA).ENDERECO_EMAIL;

                        break;
                    case 3:
                        this.nfe.infNFe.transp = new TNFe.infNFeLocalType.transpLocalType();
                        if (DOCUMENTOS_PESSOA.Any(t => t.DOCUMENTOS.COD_DOC == 1))
                        {
                            this.nfe.infNFe.transp.transporta.CPF = DOCUMENTOS_PESSOA.FirstOrDefault(t => t.DOCUMENTOS.COD_DOC == 1).VALOR_PSDC;
                        }
                        else
                        {
                            this.nfe.infNFe.transp.transporta.CNPJ = DOCUMENTOS_PESSOA.FirstOrDefault(t => t.DOCUMENTOS.COD_DOC == 2).VALOR_PSDC;
                        }

                        this.nfe.infNFe.transp.transporta.xNome = pessoa.NOME_PESSOA;
                        this.setEndereco(3, ID_ENPS);

                        if (DOCUMENTOS_PESSOA.Any(t => t.DOCUMENTOS.COD_DOC == 3))
                        {
                            this.nfe.infNFe.transp.transporta.IE = DOCUMENTOS_PESSOA.FirstOrDefault(t => t.DOCUMENTOS.COD_DOC == 3).VALOR_PSDC;
                        }

                        break;
                    case 4:
                        if (DOCUMENTOS_PESSOA.Any(t => t.DOCUMENTOS.COD_DOC == 1))
                        {
                            this.nfe.infNFe.retirada.CPF = DOCUMENTOS_PESSOA.FirstOrDefault(t => t.DOCUMENTOS.COD_DOC == 1).VALOR_PSDC;
                        }
                        else
                        {
                            this.nfe.infNFe.retirada.CNPJ = DOCUMENTOS_PESSOA.FirstOrDefault(t => t.DOCUMENTOS.COD_DOC == 2).VALOR_PSDC;
                        }

                        this.setEndereco(4, ID_ENPS);
                        break;
                    default:
                        if (DOCUMENTOS_PESSOA.Any(t => t.DOCUMENTOS.COD_DOC == 1))
                        {
                            this.nfe.infNFe.entrega.CPF = DOCUMENTOS_PESSOA.FirstOrDefault(t => t.DOCUMENTOS.COD_DOC == 1).VALOR_PSDC;
                        }
                        else
                        {
                            this.nfe.infNFe.entrega.CNPJ = DOCUMENTOS_PESSOA.FirstOrDefault(t => t.DOCUMENTOS.COD_DOC == 2).VALOR_PSDC;
                        }

                        this.setEndereco(5, ID_ENPS);
                        break;
                }

                this.SaveChanges(nf);
            }
            catch(Exception ex)
            {
                this.AddException(ex);
            }
        }

        /// <summary>
        /// Atribuir endereços aos campos da NotasFiscais de acordo ao tipo de pessoa
        /// </summary>
        /// <param name="tipo">1 - Loja
        ///                    2 - Cliente
        ///                    3 - Transportador
        ///                    4 - Endereço de retirada caso não seja o mesmo padrão da loja
        ///                    5 - Endereço de entrega caso não seja o mesmo padrão do cliente</param>
        /// <param name="ID_ENPS">Id do endereço pessoa</param>
        public void setEndereco(Int32 tipo, Int32 ID_ENPS)
        {
            xcontEntities db = new xcontEntities();

            try
            {
                Endereco endereco = this.getEndereco(ID_ENPS);

                switch (tipo)
                {
                    case 1:
                        this.nfe.infNFe.emit.enderEmit = new TEnderEmi();
                        this.nfe.infNFe.emit.enderEmit.xLgr = endereco.LOGR_END;
                        this.nfe.infNFe.emit.enderEmit.nro = endereco.NUMERO_ENPS;
                        if (!String.IsNullOrEmpty(endereco.COMPL_ENPS)) this.nfe.infNFe.emit.enderEmit.xCpl = Convertions.tString(endereco.COMPL_ENPS);
                        this.nfe.infNFe.emit.enderEmit.xBairro = endereco.NOME_BAIRRO;
                        this.nfe.infNFe.emit.enderEmit.cMun = endereco.CODIBGE_CID;
                        this.nfe.infNFe.emit.enderEmit.xMun = endereco.NOME_CID;
                        this.nfe.infNFe.emit.enderEmit.UF = endereco.SIGLA_UF;
                        this.nfe.infNFe.emit.enderEmit.CEP = endereco.CEP_END;
                        this.nfe.infNFe.emit.enderEmit.cPais = "1058";
                        this.nfe.infNFe.emit.enderEmit.xPais = "Brasil";
                        this.nfe.infNFe.emit.enderEmit.fone = endereco.NUMERO_FONE;
                        break;
                    case 2:
                        this.nfe.infNFe.dest.enderDest = new TEndereco();
                        this.nfe.infNFe.dest.enderDest.xLgr = endereco.LOGR_END;
                        this.nfe.infNFe.dest.enderDest.nro = endereco.NUMERO_ENPS;
                        if (!String.IsNullOrEmpty(endereco.COMPL_ENPS)) this.nfe.infNFe.dest.enderDest.xCpl = Convertions.tString(endereco.COMPL_ENPS);
                        this.nfe.infNFe.dest.enderDest.xBairro = endereco.NOME_BAIRRO;
                        this.nfe.infNFe.dest.enderDest.cMun = endereco.CODIBGE_CID;
                        this.nfe.infNFe.dest.enderDest.xMun = endereco.NOME_CID;
                        this.nfe.infNFe.dest.enderDest.UF = endereco.SIGLA_UF;
                        this.nfe.infNFe.dest.enderDest.CEP = endereco.CEP_END;
                        this.nfe.infNFe.dest.enderDest.cPais = "1058";
                        this.nfe.infNFe.dest.enderDest.xPais = "Brasil";
                        this.nfe.infNFe.dest.enderDest.fone = endereco.NUMERO_FONE;
                        break;
                    case 3:
                        this.nfe.infNFe.transp.transporta = new TNFe.infNFeLocalType.transpLocalType.transportaLocalType();
                        this.nfe.infNFe.transp.transporta.xEnder =
                            string.Format("{0}: {1}, {3} {4} {5}",
                                            endereco.NOME_LOGRAD,
                                            endereco.LOGR_END,
                                            endereco.NUMERO_ENPS,
                                            string.IsNullOrEmpty(endereco.COMPL_ENPS) ? string.Empty : " - " + endereco.COMPL_ENPS,
                                            " - " + endereco.NOME_BAIRRO);
                        this.nfe.infNFe.transp.transporta.xMun = endereco.NOME_CID;
                        this.nfe.infNFe.transp.transporta.UF = endereco.SIGLA_UF;
                        break;
                    case 4:
                        this.nfe.infNFe.entrega = new TLocal();
                        this.nfe.infNFe.entrega.xLgr = endereco.LOGR_END;
                        this.nfe.infNFe.entrega.nro = endereco.NUMERO_ENPS;
                        if (!String.IsNullOrEmpty(endereco.COMPL_ENPS)) this.nfe.infNFe.entrega.xCpl = Convertions.tString(endereco.COMPL_ENPS);
                        this.nfe.infNFe.entrega.xBairro = endereco.NOME_BAIRRO;
                        this.nfe.infNFe.entrega.cMun = endereco.CODIBGE_CID;
                        this.nfe.infNFe.entrega.xMun = endereco.NOME_CID;
                        this.nfe.infNFe.entrega.UF = endereco.SIGLA_UF;
                        break;
                    default:
                        this.nfe.infNFe.retirada = new TLocal();
                        this.nfe.infNFe.retirada.xLgr = endereco.LOGR_END;
                        this.nfe.infNFe.retirada.nro = endereco.NUMERO_ENPS;
                        if (!String.IsNullOrEmpty(endereco.COMPL_ENPS)) this.nfe.infNFe.retirada.xCpl = Convertions.tString(endereco.COMPL_ENPS);
                        this.nfe.infNFe.retirada.xBairro = endereco.NOME_BAIRRO;
                        this.nfe.infNFe.retirada.cMun = endereco.CODIBGE_CID;
                        this.nfe.infNFe.retirada.xMun = endereco.NOME_CID;
                        this.nfe.infNFe.retirada.UF = endereco.SIGLA_UF;
                        break;
                }
            }
            catch (Exception ex)
            {
                this.AddException(ex);
            }
        }

        /// <summary>
        /// Retorna os dados de endereço da entidade com base no id
        /// </summary>
        /// <param name="ID_ENPS">ID_ENPS</param>
        /// <returns></returns>
        private Endereco getEndereco(Int32 ID_ENPS)
        {
            xcontEntities db = new xcontEntities();

            return (from c in db.ENDERECOS_PESSOA
                    where c.ID_ENPS == ID_ENPS
                    select new Endereco
                    {
                        CEP_END = c.ENDERECOS.CEP_END,
                        NOME_LOGRAD = c.ENDERECOS.LOGRADOUROS.NOME_LOGRAD,
                        CODIBGE_CID = c.ENDERECOS.BAIRROS.CIDADES.CODIBGE_CID,
                        NUMERO_FONE = c.PESSOAS.TELEFONES.Any() ? c.PESSOAS.TELEFONES.FirstOrDefault().NUMERO_FONE : string.Empty,
                        NUMERO_ENPS = c.NUMERO_ENPS,
                        SIGLA_UF = c.ENDERECOS.BAIRROS.CIDADES.UFS.SIGLA_UF,
                        NOME_BAIRRO = c.ENDERECOS.BAIRROS.NOME_BAIRRO,
                        COMPL_ENPS = c.COMPL_ENPS,
                        LOGR_END = c.ENDERECOS.LOGR_END,
                        NOME_CID = c.ENDERECOS.BAIRROS.CIDADES.NOME_CID
                    }).First();
        }

        /// <summary>
        /// Parametros de Endereço
        /// </summary>
        private class Endereco
        {
            public String CEP_END { get; set; }
            public String NOME_LOGRAD { get; set; }
            public String CODIBGE_CID { get; set; }
            public String NUMERO_FONE { get; set; }
            public String NUMERO_ENPS { get; set; }
            public String SIGLA_UF { get; set; }
            public String NOME_BAIRRO { get; set; }
            public String COMPL_ENPS { get; set; }
            public String LOGR_END { get; set; }
            public String NOME_CID { get; set; }
        }
    }
}